<?php

class Object{

    /**
     * @abstract mensagens de execussao
     */
    private $object_msg = array();

    /**
     * @abstract configuracoes da classe
     */
    protected $config;

    /**
     * @abstract seta uma nova mensagem de erro
     * @param string $msg   mensagem de erro
     * @return nada
     */
    public function setErrorMessage($msg){
        $this->setMessage("erro", $msg);
    }

    /**
     * @abstract seta uma nova mensagem de sucesso
     * @param string $msg   mensagem de sucesso
     * @return nada
     */
    public function setSuccessMessage($msg){
        $this->setMessage("success", $msg);
    }
    
    public function setMessages($msgs){
        if(is_array($msgs) && !empty ($msgs)) {
            $this->object_msg = array_merge($this->object_msg, $msgs);
        }
    }
    
    public function setAlertMessage($msg){
        $this->setMessage("alert", $msg);
    }
    
    /**
     * @abstract seta uma nova mensagem
     * @param string $camp  nome da variável de mensagem
     * @param string $msg   mensagem da variável
     * @return nada
     */
    public function setMessage($camp, $msg){
        $this->object_msg[$camp] = $msg;
    }
    
    public function addLog($msg){
        $this->object_msg['log'][] = $msg;
    }
    
    public function getLog(){
        return $this->object_msg['log'];
    }
    
    /**
      * @abstract retorna as mensagens de erro
      * @return string
      */
     public function getErrorMessage(){
         
         $var = "";
     	 if(is_array($this->object_msg)){
             if(array_key_exists("erro", $this->object_msg)){
                $var = $this->object_msg['erro'];
             }
         }
         return $var;
     }

     /**
      * @abstract retorna string contendo as mensagens de sucesso caso existam
      * @return string
      */
     public function getSuccessMessage(){
     	 if(is_array($this->object_msg)){
             if(array_key_exists("success", $this->object_msg)){
                return $this->object_msg['success'];
             }
         }
     }
     
     public function getAlertMessage(){
     	 if(is_array($this->object_msg)){
             if(array_key_exists("alert", $this->object_msg)){
                return $this->object_msg['alert'];
             }
         }
     }

    /**
    * @abstract array contendo todas as mensagens da classe
    * @return array
    */
    public function getMessages(){
        return $this->object_msg;
    }
    
    /*retorna o nome da classe que foi chamada primeiro*/
    public static function whoAmI() {
        return get_called_class();
    }

    /**
    * @abstract Carrega o um model para dentro da classe model
    * @uses Carrega o um model para dentro da classe model
    * @param string @model  Nome do arquivo do model a ser carregado
    * @param string $name   Nome do objeto a ser criado, caso nao seja informado o objeto
                              terá o nome do proprio model
    * @throws Exception 
    * @return não retorna nada
    */
    public function LoadModel($modelname, $name, $throws = true){
        
        //seta o modulo e a pasta do modulo
        $model  = explode("/",$modelname);
        $plugin = array_shift($model);
        $modulo = array_shift($model);
        $class  = array_pop($model);
        if($class == ""){
            $class = $plugin."_".$modulo;
            $file  = $modulo;
        }else{
            $file   = $class;
            $class  = $plugin."_".$class;
        }
        $class .= "Model";
        $file  .= "Model";
        $path   = implode("/", $model);
        $path   = ($path == "")? "": $path . "/";
        
        //procura o arquivo
        $folder = MODULOS . "$plugin/$modulo/classes/$path$file.php";
        if(!file_exists($folder)){
            if($throws){
                $str = "";
                if(DEBUG){
                    $erro = error_get_last();
                    $dbg  = "";
                    if(!empty($erro)){
                        $dbg = "<br/><br/><b>Sobre a chamada:</b> <br/> ";
                        foreach($erro as $nm => $v){
                            $dbg .= "<b>$nm</b>: $v<br/>";
                        }
                    }
                    $str = "<br/><b>Arquivo procurado:</b> ($folder) $dbg";
                }
                throw new Exception("O Model ($class) não foi encontrado ou não existe $str");
            }
            $this->$name = NULL;
            return $this->$name;
        }
        $this->LoadConfigFromPlugin($plugin);
        require_once $folder;
        
        if(!class_exists($class)){
            if($throws) throw new Exception("A classe ($class) não foi encontrado ou não existe");
            $this->$name = NULL;
            return $this->$name;
        }
        
        $this->$name = new $class();
        if(!is_object($this->$name)){
            if($throws) throw new Exception("Não foi possível instanciar o Model $class");
            $this->$name = NULL;
            return $this->$name;
        }
        if(method_exists($this->$name, 'setModelName')) $this->$name->setModelName($modelname);
        return $this->$name;
    }
    
    public function LoadClassFromPlugin($ClassName, $name, $throws = true){
        
        $model  = explode("/",$ClassName);
        $plugin = array_shift($model);
        $modulo = array_shift($model);
        $class  = array_pop($model);
        $class  = (($class == "")?$modulo:$class);
        $path   = implode("/", $model);
        $path   = ($path == "")? "": $path . "/";
        
        $folder = MODULOS . "$plugin/$modulo/classes/$path$class.php";
        if(!file_exists($folder)){
            if($throws) throw new Exception("O arquivo da classe ($class) não foi encontrada ou não existe");
            $this->$name = NULL;
            return;
        }
        
        $this->LoadConfigFromPlugin($plugin);
        require_once $folder;

        if(!class_exists($class)){
            $class = "{$plugin}_{$class}";
            if(!class_exists($class)){
                if($throws) throw new Exception("A classe ($class) não foi encontrado ou não existe");
                $this->$name = NULL;
                return;
            }
            
        }
        
        $this->$name = new $class();
        if(!is_object($this->$name)){
            if($throws) throw new Exception("Não foi possível instanciar a Classe $class");
            $this->$name = NULL;
            return;
        }
    }
    
    /**
    * @abstract Carrega o um recurso
    * @uses Carregar um recurso
    * @param string $resource Recebe uma string com o nome do recurso a ser carregado
    * @param string $name     Recebe uma string com o nome do objeto
    * @throws Exception 
    * @return não retorna nada
    */
    public function LoadResource($resource, $name){
        $file = RESOURCES . "$resource"."Resource.php";
        $explode = explode("/", $resource);
        $explode = end($explode);
        $class    = $explode . "Resource";
        //echo "\n ($class) \n";
        if(!file_exists($file)){
            
            $msg  = __CLASS__ . ": O recurso $resource não existe! <br/> Diretório procurado: $file";
            $file = RESOURCES . "$resource/$class".".php";
            
            if(!file_exists($file)){
                $msg  .= "<br/> Diretório procurado: $file";
                throw new Exception($msg);
            }
        }
        $this->LoadConfigFromResource($resource);
        require_once $file;
        
        $this->CheckClass($class);
        $obj = call_user_func("$class::getInstanceOf");
        
        if(!is_object($obj)){
            if(!is_object($obj)){
                throw new Exception(__CLASS__ . ": Não foi possível carregar o Recurso $resource");
            }
        }
        $this->$name = $obj;
        return $obj;
    }
    
    /**
    * @abstract Carrega um plugin javascript para dentro da classe model
    * @param string @plugin  Nome do arquivo do plugin a ser carregado
    * @param string $name   Nome do objeto a ser criado, caso nao seja informado o objeto
                              terá o nome do proprio model
    * @throws Exception 
    * @return não retorna nada
    */
    public function LoadJsPlugin($plugin, $name, $scripts = true){
        
        $pvar = $plugin;
        //seta o modulo e a pasta do modulo
        $plugin  = explode("/",$plugin);
        $resource = array_shift($plugin);
        $modulo = array_shift($plugin);
        $class  = array_pop($plugin);
        $class  = (($class == "")?$modulo:$class)."Js";
        $path   = implode("/", $plugin);
        $path   = ($path == "")? "": $path . "/";
        
        //procura o arquivo
        $this->LoadConfigFromResource($resource);
        $folder = RESOURCES . "$resource/jsplugins/$modulo/$path$class.php";
        $this->LoadFile($folder);
        $this->CheckClass($class);
        
        $obj = call_user_func("$class::getInstanceOf", $pvar);
        if(!is_object($obj)) 
            throw new Exception(__CLASS__ . ": Não foi possível instanciar o Plugin javascript $class");
        $obj->start_scripts($scripts);
        $this->$name = $obj;
        return $obj;
    }
    
    /**
    * @abstract Carrega um componente da pasta de um plugin
    */
    public function LoadComponent($component, $name){
        
        //seta o modulo e a pasta do modulo
        $component = explode("/",$component);
        $plugin = array_shift($component);
        $modulo = array_shift($component);
        $class  = array_pop($component);
        $class  = (($class == "")?$modulo:$class)."Component";
        $path   = implode("/", $component);
        $path   = ($path == "")? "": $path . "/";
        
        //procura o arquivo
        $folder = MODULOS . "$plugin/$modulo/components/$path$class.php";
        $classname = $class;
        if(!file_exists($folder)){
            $folder = MODULOS . "$plugin/$modulo/classes/$path$class.php";
            if(!file_exists($folder)) $classname = "Component";
            else require_once $folder;
        }
        else {
            $this->LoadConfigFromPlugin($plugin);
            require_once $folder;
        }
        
        $this->$name = new $classname();
        if(!is_object($this->$name)){
            throw new Exception("Não foi possível instanciar o Componente $class");
        }
        return $this->$name ;
    }
    
    public function LoadFile($folder){
        if(!file_exists($folder)) 
            throw new Exception("O arquivo $folder não foi encontrado!");
        require_once $folder;
    }
    
    public function LoadConfigFromPlugin($plugin){
        static $loaded = array();
        if(in_array($plugin, $loaded)) return;
        $loaded[] = $plugin;

        $this->LoadAllFilesFromDir(MODULOS . "$plugin/Config/defines");
        $this->LoadAllFilesFromDir(MODULOS . "$plugin/Config/interfaces");

    }

    public function LoadConfigFromResource($resource){
        if($resource == "files/dir") return;
        static $loaded = array();
        if(in_array($resource, $loaded)) return;
        $loaded[] = $resource;
        $this->LoadAllFilesFromDir(RESOURCES . "$resource/defines");
        $this->LoadAllFilesFromDir(RESOURCES . "$resource/interfaces");
    }
    
    private function LoadAllFilesFromDir($diretorio){
        $this->LoadResource('files/dir', "object_temp_dir_obj");
        $files = $this->object_temp_dir_obj->getArquivos($diretorio);
        if(!empty ($files)){
            foreach($files as $fname){
                $dir = $diretorio . "/$fname";
                if(file_exists($dir)) require_once $dir;
            }
        }
    }
    
    public function CheckClass($class){
        if(!class_exists($class, false))
            throw new Exception("A classe $class não existe");
    }
    
}

?>